package com.share.example.classload.config;

import com.share.common.utils.ClassUtil;
import com.share.common.utils.EncryptUtil;
import com.share.common.utils.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.File;
import java.util.List;

@Slf4j
@Component
public class LoadOutFileClassConfig extends ClassLoader {
    @Value("${encryptClassDirHome}")
    private String encryptClassDirHome;

    @Value("${encryptClassPackage:\\}")
    private String encryptClassPackage;
    private String encryptClassPackageDir;

    @Autowired
    private ServiceImplRegistry serviceImplRegistry;

    /**
     * 系统会自动调用这个方法
     *
     * @param name
     * @return
     * @throws ClassNotFoundException
     */
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] bytes = FileUtil.readByte(name);
        byte[] decryptBytes = EncryptUtil.decrypt(bytes);
        int len = decryptBytes.length;

        log.info("正在被加载fileName={},len={}", name, len);
        return defineClass(null, decryptBytes, 0, len);
    }

//    @Override
//    public Class<?> loadClass(String name) throws ClassNotFoundException {
//        log.info("这个类正在被加载fileName={}", name);
//        return super.loadClass(name);
//    }

    @PostConstruct
    public void loadClassToJvm() {
        log.info("入参配置encryptClassDirHome={},encryptClassPackage={}",encryptClassDirHome,encryptClassPackage);
        this.encryptClassPackageDir = encryptClassPackage.replaceAll("\\.", File.separator + File.separator);

        log.info("###正在初始化类加载###");
        List<File> fileList = FileUtil.listFile(encryptClassDirHome);
        for (File file : fileList) {
            String fileName = file.getAbsolutePath();
            if (file.isFile() && fileName.endsWith(".class")) {
                try {
                    //赛选跳过特定的类
                    boolean contains = fileName.contains(encryptClassPackageDir);
                    if (!contains) {
                        continue;
                    }

                    //手动触发去加载类
                    Class<?> aClass = findClass(fileName);

                    //提取参数校验
                    boolean localClass = true;
                    Service service = aClass.getAnnotation(Service.class);
                    Component component = aClass.getAnnotation(Component.class);
                    if (localClass && (service != null || component != null)) {
                        List<Class<?>> interfacesList = ClassUtil.listSuperInterfaces(aClass);
                        Class<?> interaceClazz = interfacesList.get(0);
                        serviceImplRegistry.registerBean(aClass, interaceClazz);
                    }
                } catch (Exception e) {
                    log.error("加载class并注入spring容器异常", e);
                }
            }
        }
        log.info("###类加载完毕###");
    }
}
